package heap

import (
	"jvm/classfile"
	. "jvm/typedef"
	"strings"
)

type Class struct {
	accessFlags    U2
	name           string //全类名 如 java.lang.Object --> java/lang/Object
	superClassName string
	interfaceNames []string

	constantPool      *ConstantPool
	fields            []Field
	methods           []Method
	loader            *ClassLoader
	superClass        *Class
	interfaces        []*Class
	instanceSlotCount U4
	staticSlotCount   U4
	staticVars        Slots
	isInitialization  bool
}

// **************************************************
func newClass(cf classfile.ClassFile) *Class {
	class := &Class{}
	class.accessFlags = cf.AccessFlags()
	class.name = cf.ClassName()
	class.superClassName = cf.SuperClassName()
	class.interfaceNames = cf.InterfaceNames()
	//constantPool
	class.constantPool = newConstantPool(class, cf.ConstantPool())
	//fields
	class.fields = newFields(class, cf.Fields())
	//methods
	class.methods = newMethods(class, cf.Methods())
	//
	class.isInitialization = false
	return class
}

func (self *Class) getField(name string, descroptor string, isStatic bool) *Field {
	for c := self; c != nil; c = c.superClass {
		for _, field := range c.fields {
			if field.IsStatic() == isStatic &&
				field.name == name &&
				field.descriptor == descroptor {
				return &field
			}
		}
	}
	return nil
}

// **************************************************
// 返回该类的数组类
func (self *Class) ArrayClass() *Class {
	descriptor := ""
	if self.name[0] == '[' {
		descriptor = self.name
	} else {
		descriptor = "L" + self.name + ";"
	}
	arrayClassName := "[" + descriptor
	return self.loader.LoadClass(arrayClassName)
}

// **************************************************
// 创建类的实例对象
func (self *Class) NewObject() *Object {
	return newObject(self)
}

// **************************************************
// 获取类的初始化方法
func (self *Class) GetClinitMethod() *Method {
	for _, method := range self.methods {
		if method.IsStatic() && method.name == "<clinit>" && method.descriptor == "()V" {
			return &method
		}
	}
	return nil
}

// **************************************************
// 检查self是否可以访问class
// 1.若class是public的，self可以访问
// 2.若class是default的，self与class在同一个包下可以访问，否则不行
func (self *Class) isAccessibleTo(class *Class) bool {
	if self.IsPublic() {
		return true
	}
	if self.PackageName() == class.PackageName() {
		return true
	}
	return false
}

// 判断self是否是class的子类
func (self *Class) IsSubClassOf(class *Class) bool {
	for c := self.superClass; c != nil; c = c.superClass {
		if c == class {
			return true
		}
	}
	return false
}

// 判断self是否实现了iface
func (self *Class) IsImplements(iface *Class) bool {
	for c := self; c != nil; c = c.superClass {
		for _, i := range c.interfaces {
			if iface == i || i.isSubInterfaceOf(iface) {
				return true
			}
		}
	}
	return false
}

// 判断self是否是iface的子接口
func (self *Class) isSubInterfaceOf(iface *Class) bool {
	for _, i := range self.interfaces {
		if i == iface || i.isSubInterfaceOf(iface) {
			return true
		}
	}
	return false
}

// 获取类的包名
func (self *Class) PackageName() string {
	index := strings.LastIndex(self.name, "/")
	if index == -1 {
		return ""
	}
	return self.name[:index]
}

func (self *Class) isAssignableFrom(other *Class) bool {
	s, t := other, self
	if s == t {
		return true
	}
	if !s.IsArray() {
		if !s.IsInterface() {
			// s is class
			if !t.IsInterface() {
				// t is not interface
				return s.IsSubClassOf(t)
			} else {
				// t is interface
				return s.IsImplements(t)
			}
		} else {
			// s is interface
			if !t.IsInterface() {
				// t is not interface
				return t.isJlObject()
			} else {
				// t is interface
				return s.isSubInterfaceOf(t)
			}
		}
	} else {
		// s is array
		if !t.IsArray() {
			if !t.IsInterface() {
				// t is class
				return t.isJlObject()
			} else {
				// t is interface
				return t.isJlCloneable() || t.isJioSerializable()
			}
		} else {
			// t is array
			sc := s.ElementClass()
			tc := t.ElementClass()
			return sc == tc || tc.isAssignableFrom(sc)
		}
	}
	return false
}
func (self *Class) isJlObject() bool {
	return self.name == "java/lang/Object"
}
func (self *Class) isJlCloneable() bool {
	return self.name == "java/lang/Cloneable"
}
func (self *Class) isJioSerializable() bool {
	return self.name == "java/io/Serializable"
}

// **************************************************
// getter
func (self *Class) ConstantPool() *ConstantPool {
	return self.constantPool
}
func (self *Class) StaticVars() Slots {
	return self.staticVars
}
func (self *Class) Methods() []Method {
	return self.methods
}
func (self *Class) SuperClass() *Class {
	return self.superClass
}
func (self *Class) Name() string {
	return self.name
}
func (self *Class) IsInitialization() bool {
	return self.isInitialization
}

func (self *Class) Loader() *ClassLoader {
	return self.loader
}

// setter
func (self *Class) SetInitialization() {
	self.isInitialization = true
}

// **************************************************
// 访问标记相关
func (self *Class) IsPublic() bool {
	return 0 != self.accessFlags&ACC_PUBLIC
}
func (self *Class) IsFinal() bool {
	return 0 != self.accessFlags&ACC_FINAL
}
func (self *Class) IsSuper() bool {
	return 0 != self.accessFlags&ACC_SUPER
}
func (self *Class) IsInterface() bool {
	return 0 != self.accessFlags&ACC_INTERFACE
}
func (self *Class) IsAbstract() bool {
	return 0 != self.accessFlags&ACC_ABSTRACT
}
func (self *Class) IsSynthetic() bool {
	return 0 != self.accessFlags&ACC_SYNTHETIC
}
func (self *Class) IsAnnotation() bool {
	return 0 != self.accessFlags&ACC_ANNOTATION
}
func (self *Class) IsEnum() bool {
	return 0 != self.accessFlags&ACC_ENUM
}

// **************************************************
